module Executs32(
    //from decoder
    input[31:0] Read_data_1,//the source of Ainput
    input[31:0] Read_data_2,//one of the source of Binput
    input[31:0] Imme_extend,//one of the source of Binput Address


    //from ifetch
    input[5:0] Function_opcode,//instruction[5:0]
    input[5:0] opcode, //instruction[31:26]
    input[4:0] Shamt, //instruction[10:6], the amount of Shamt
    input[31:0] PC_plus_4, //pc+4

    //from controller
    input[1:0] ALUOp,
    input ALUSrc,//1->2nd oprand is an immediate
    input I_format,//1-> I-format except beq,bne,LW,SW
    input Sftmd,//1->shift instruction
    input Jr,//1->jr instruction

    output Zero,
    output reg[31:0] ALU_Result,//the calculated result
    output[31:0] Addr_Result//the calculated address
);


wire[31:0] Ainput,Binput;//two oprands

wire[2:0] ALU_ctrl;//ALU control signal which affect the operation of ALU
wire[2:0] Sftm;//determine the types of shift instruction,equal to the Function_code[2:0]
reg[31:0] ALU_output_mux;//the result of arithmetic or logic calculation
reg[31:0] Shift_Result;//the result of shift operation

wire[32:0] Branch_Addr;//the calculated address of the instruction

wire[5:0] ctrl_code;
//assign Read_data_1 to the Ainput
assign Ainput = Read_data_1;
//assign Read_data_2 to the Binput
assign Binput = (ALUSrc == 0) ? Read_data_2 : Imme_extend[31:0];
//generate the 2nd level control signal
assign ctrl_code = (I_format == 0) ? Function_opcode : {3'b000, opcode[2:0]};
//generate the 3nd level control signal
assign ALU_ctrl[0] = (ctrl_code[0] | ctrl_code[3]) & ALUOp[1];
assign ALU_ctrl[1] = ((!ctrl_code[2])|(!ALUOp[1]));
assign ALU_ctrl[2] = (ctrl_code[1] & ALUOp[1]) | ALUOp[0];
//distinguish the left or right shift operation
assign Sftm = Function_opcode[2:0];
//the result of arithmatic or logical calculation
always @(ALU_ctrl or Ainput or Binput) 
begin
    case(ALU_ctrl)
        3'b000: ALU_output_mux = Ainput & Binput;
        3'b001: ALU_output_mux = Ainput | Binput;
        3'b010: ALU_output_mux = Ainput + Binput;
        3'b011: ALU_output_mux = Ainput + Binput;
        3'b100: ALU_output_mux = Ainput ^ Binput;
        3'b101: ALU_output_mux = ~(Ainput | Binput);
        3'b110: ALU_output_mux = Ainput - Binput;
        3'b111: ALU_output_mux = Ainput - Binput;
        default: ALU_output_mux = 32'h00000000;
    endcase
    
end
//six shift instruction
//锛侊紒锛�
always @(*) 
begin
if(Sftmd)
    case(Sftm[2:0])
        3'b000: Shift_Result = Binput << Shamt;
        3'b010: Shift_Result = Binput >> Shamt;
        3'b100: Shift_Result = Binput << Ainput;
        3'b110: Shift_Result = Binput >> Ainput;
        3'b011: Shift_Result = $signed(Binput) >>> Shamt;
        3'b111: Shift_Result = $signed(Binput) >>> Ainput;
        default: Shift_Result = Binput;
    endcase
else
    Shift_Result = Binput;
end

//PC-relative
assign Branch_Addr = (PC_plus_4 >> 2) + Imme_extend[31:0];

//zero
assign Zero = (ALU_output_mux == 32'h00000000) ? 1'b1 : 1'b0;

//addr_result
assign Addr_Result = Branch_Addr[31:0];

//ALU_Result
always @* begin
    //set type operation (slt, slti, sltu, sltiu)
    if(((ALU_ctrl==3'b111) && (ctrl_code[3]==1))||((ALU_ctrl[2:1]==2'b11) && (I_format==1)))
        ALU_Result = (ALU_output_mux[31]==1)?1:0;
    //lui operation
    else if((ALU_ctrl==3'b101) && (I_format==1))
        ALU_Result[31:0]={Binput[15:0],{16{1'b0}}};
    //shift operation
    else if(Sftmd==1)
        ALU_Result = Shift_Result ;
    //other types of operation in ALU (arithmatic or logic calculation)
    else
        ALU_Result = ALU_output_mux[31:0];
end



endmodule